package com.xdxc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xdxc.exception.CustomException;
import com.xdxc.feign.QuestionFeign;
import com.xdxc.model.dto.ExamSaveDTO;
import com.xdxc.model.dto.PaperDto;
import com.xdxc.model.dto.QuestionPaperDto;
import com.xdxc.model.entity.ExamPaper;
import com.xdxc.model.entity.Paper;
import com.xdxc.mapper.PaperMapper;
import com.xdxc.model.entity.QuestionGroup;
import com.xdxc.model.entity.UserAnswer;
import com.xdxc.response.Result;
import com.xdxc.service.ExamPaperService;
import com.xdxc.service.PaperService;
import com.xdxc.service.QuestionGroupService;
import com.xdxc.utils.RandomIdGenerator;
import com.xdxc.utils.SecurityUtils;
import com.xdxc.utils.TokenManager;
import com.xdxc.vo.QuestionWithOptionsVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper> implements PaperService {

    @Autowired
    private ExamPaperService examPaperService;

    @Autowired
    private QuestionGroupService questionGroupService;

    @Autowired
     private QuestionFeign questionFeign;
    @Autowired
    private RedisService redisService;


    @Autowired
    private TokenManager tokenManager;

    @Override
    @Transactional
    public boolean savePaper(PaperDto examPaperDto) {
        ExamPaper examPaper = examPaperService.getById(examPaperDto.getId());
        if (examPaper != null) {
            throw new CustomException(400, "试卷已存在");
        }
        ExamPaper examPaper1 = new ExamPaper();
        Long paperId= new  RandomIdGenerator(2,5).generateId();
        examPaper1.setId(paperId);
        examPaper1.setPaperDuration(examPaperDto.getPaperDuration());
        examPaper1.setPaperName(examPaperDto.getPaperName());
        examPaper1.setScore(examPaperDto.getScore());
        examPaperService.save(examPaper1);
        List<QuestionGroup> questionGroups = new ArrayList<>();
        List<Paper> papers = new ArrayList<>();
        RandomIdGenerator randomIdGenerator= new  RandomIdGenerator(2,5);
        // 生成所有 QuestionGroup 并分配 ID
        examPaperDto.getQuestionGroupList().stream()
                .filter(Objects::nonNull)
                .forEach(groupDto -> {
                    QuestionGroup group = new QuestionGroup();
                    group.setPaperId(paperId);
                    group.setId(randomIdGenerator.generateId()); // 使用分布式ID生成器
                    group.setTitle(groupDto.getQuTypeDictText());
                    questionGroups.add(group);
                });
        // 批量保存 QuestionGroup
        questionGroupService.saveBatch(questionGroups);
        // 处理每个组及其题目
        int groupIndex = 0;
        AtomicInteger sortOrder = new AtomicInteger(1);

        for (QuestionGroup groupDto : examPaperDto.getQuestionGroupList()) {
            if (groupDto == null) continue;
            QuestionGroup currentGroup = questionGroups.get(groupIndex++);

            // 方法2的应用
            List<Paper> groupPapers = groupDto.getQuList().stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            QuestionWithOptionsVo::getId,
                            question -> {
                                Paper paper = new Paper();
                                paper.setPaperId(paperId);
                                paper.setQuId(question.getId());
                                paper.setQuType(question.getQuType());
                                paper.setQuTypeDictText(question.getQuTypeDictText());
                                paper.setScore(question.getScore());
                                paper.setSort(sortOrder.getAndIncrement());
                                paper.setGroupId(currentGroup.getId());
                                return paper;
                            },
                            (existing, replacement) -> existing
                    ))
                    .values()
                    .stream()
                    .collect(Collectors.toList());
            papers.addAll(groupPapers);
        }
        if (papers.isEmpty()) {
            throw new CustomException(400, "试卷题目不能为空");
        }
        this.saveBatch(papers);
        return true;
    }

    @Override
    public List<QuestionWithOptionsVo> getPaperQuestion(List<Paper> paperList) {
        List<Long> idList= paperList.stream().map(Paper::getQuId).collect(Collectors.toList());


       String token= tokenManager.getToken();
        Result<List<QuestionWithOptionsVo>>  questionWithOptionsVoResult= questionFeign.getBatchQuestions("Bearer "+token,idList);
        if (questionWithOptionsVoResult.getCode()!=1){
            throw new  CustomException(500,"服务器出错了");
        }

        return questionWithOptionsVoResult.getData();
    }

    @Override
    public PaperDto getPaperExam(Long paperId) {
        ExamPaper examPaper = examPaperService.getById(paperId);
        if (examPaper == null) {
            throw new CustomException(400, "试卷不存在");
        }
        List<Paper> paperList= this.list(new LambdaQueryWrapper<Paper>().eq(Paper::getPaperId,paperId));
        if (paperList.size()==0){
            PaperDto paperDto=PaperDto.builder()
                    .paperName(examPaper.getPaperName())
                    .paperDuration(examPaper.getPaperDuration())
                    .paperOrder(examPaper.getPaperOrder())
                    .score(examPaper.getScore())
                    .createTime(examPaper.getCreateTime())
                    .id(examPaper.getId())
                    .questionGroupList(null)
                    .build();
            return paperDto;
        }
        List<QuestionGroup> questionGroupList= this.questionGroup(paperId,paperList);

        PaperDto paperDto=PaperDto.builder()
            .paperDuration(examPaper.getPaperDuration())
            .paperOrder(examPaper.getPaperOrder())
            .paperName(examPaper.getPaperName())
            .createTime(examPaper.getCreateTime())
            .id(examPaper.getId())
            .questionGroupList(questionGroupList)
            .score(examPaper.getScore())
            .build();
        return paperDto;
    }

    @Override
    public Result editExamPaper(ExamSaveDTO examSaveDTO) {
        ExamPaper examPaper = examPaperService.getById(examSaveDTO.getId());
        if (examPaper == null) {
            throw new CustomException(401, "something Broke");
        }
        // 2. 处理删除操作（存在显式删除时）
        if (!examSaveDTO.getDeletedQuestions().isEmpty()) {
            this.removeByIds(examSaveDTO.getDeletedQuestions());
        }
        // 3. 生成增量操作集合
        List<Paper> currentQuestions = this
                .list(new QueryWrapper<Paper>()
                        .eq("paper_id", examSaveDTO.getId()));
        Map<Long, Paper> existingMap = currentQuestions.stream()
                .collect(Collectors.toMap(Paper::getQuId, Function.identity()));
        List<Paper> toUpdate = new ArrayList<>();
        List<Paper> toInsert = new ArrayList<>();
        for (ExamSaveDTO.QuestionGroup questionGroup : examSaveDTO.getQuestionGroups()) {
            for (Paper paper : questionGroup.getPapers()) {
                if (existingMap.containsKey(paper.getQuId())) {
                    // 更新排序
                    Paper paper1 = existingMap.get(paper.getId());
                    if (paper.getSort().equals(paper1.getSort())) {
                        paper1.setSort(paper.getSort());
                        toUpdate.add(paper1);
                    }
                } else {
                    // 新增关联
                    toInsert.add(
                            new Paper().builder()
                                    .paperId(paper.getPaperId())
                                    .quId(paper.getQuId())
                                    .quType(paper.getQuType())
                                    .score(paper.getScore())
                                    .groupId(paper.getGroupId())
                                    .quType(paper.getQuType())
                                    .sort(paper.getSort())
                                    .build());
                }
            }
            // 4. 批量执行操作
            if (!toInsert.isEmpty()) {
                this.saveBatch(toInsert); // 自定义批量插入
            }
            if (!toUpdate.isEmpty()) {
                this.updateBatchById(toUpdate); // 自定义批量更新
            }
        }
        return null;
    }

    public List<QuestionGroup> questionGroup(Long paperId,List<Paper> paperList){
        Map<Long, Paper> paperListMap= paperList.stream().collect(Collectors.toMap(Paper::getQuId,p->p,(existing, replacement) -> existing));
        CompletableFuture< List<QuestionGroup>> questionGroupFuture = CompletableFuture.supplyAsync(() ->
                questionGroupService.list(new LambdaQueryWrapper<QuestionGroup>().eq(QuestionGroup::getPaperId,paperId)));
        Map<Long,List<QuestionPaperDto>>  questionWithOptionsVoMap =this.getPaperQuestion(paperList).stream().map(questionWithOptionsVo -> {
            QuestionPaperDto questionPaperDto = new QuestionPaperDto();
            BeanUtils.copyProperties(questionWithOptionsVo,questionPaperDto);
            Paper paper = Optional.ofNullable(paperListMap.get(questionWithOptionsVo.getQuId()))
                    .orElseThrow(() -> new CustomException(500,"试卷题目关联信息缺失"));
            questionPaperDto.setScore(paper.getScore());
            questionPaperDto.setSort(paper.getSort());
            questionPaperDto.setGroupId(paper.getGroupId());
            questionPaperDto.setAnswerOrder(paper.getAnswerOrder());
            questionPaperDto.setQuTypeDictText(paper.getQuTypeDictText());
            questionPaperDto.setQuType(paper.getQuType());
            return questionPaperDto;
        }).collect(Collectors.groupingBy(QuestionPaperDto::getGroupId));

        return questionGroupFuture.join().stream()
                .filter(Objects::nonNull)
                .peek(questionGroup -> {
                    questionGroup.setQuList(questionWithOptionsVoMap.get(questionGroup.getId()));
                }).collect(Collectors.toList());
    }

    @Override
     public   List<Paper>  returnPaperWithUserAnswer(Long examRecordId, Long paperId){
       Long userId= SecurityUtils.getCurrentUserId();
        CompletableFuture<List<Paper>> relationFuture =  CompletableFuture.supplyAsync(() ->
                this.list(new LambdaQueryWrapper<Paper>().eq(Paper::getPaperId, paperId))
        );
        Map<Long, UserAnswer> userAnswersMap = redisService.hashGetAll(examRecordId +"_"+userId)
                .entrySet()
                .stream().collect(Collectors.toMap(
                        e -> Long.parseLong(e.getKey().toString()),
                        e -> (UserAnswer) e.getValue()
                ));
        // 如果 userAnswersMap 为空，初始化一个空的 HashMap
        if (userAnswersMap == null) {
            userAnswersMap = new HashMap<>();
        }
        List<Paper> paperList=relationFuture.join();
        // 6. 数据加工处理
        // 遍历每个Paper，设置是否已回答
        for (Paper paper : paperList) {
            // 检查是否有用户答案
            UserAnswer userAnswersForCurrentQuestion = userAnswersMap.get(paper.getId());
            // 如果没有用户答案，标记为未回答
            if (userAnswersForCurrentQuestion == null ) {
                paper.setAnswered(false);
            } else {
                // 遍历所有用户答案，检查是否有已勾选且答案为空的情况
                boolean allAnswered = userAnswersForCurrentQuestion.getAnswerIds().size()!=0 || userAnswersForCurrentQuestion.getAnswerText() != null;
                // 如果有有效的答案，则标记为已回答
                paper.setAnswered(allAnswered);
            }
        }
        return paperList;
    }
    }

